package com.lxw.multidb.modules.file;

import java.util.Date;
import java.util.List;

/**
 * 目录树服务工具类
 * <p>
 * 提供路径处理、过滤、排序等公共方法
 *
 * @author lxw
 * @version 3.0
 * @date 2025-11-06
 */
public class TreeServiceUtils {

    private static final String PATH_SEPARATOR = "/";

    // ==================== 路径处理 ====================

    /**
     * 标准化路径前缀
     * <p>
     * 规则：
     * - null或空返回空串
     * - 将\转换为/
     * - 处理多个连续/为单个/
     * - 移除末尾/
     * <p>
     * 示例：
     * - "C:\\Users\\test\\" → "C:/Users/test"
     * - "data///files//" → "data/files"
     */
    public static String normalizePath(String path) {
        if (path == null || path.isEmpty()) {
            return "";
        }
        path = path.replace("\\", PATH_SEPARATOR);
        path = path.replaceAll("(/)\\1{1,}", "$1");
        if (path.endsWith(PATH_SEPARATOR) && path.length() > 1) {
            path = path.substring(0, path.length() - 1);
        }
        return path;
    }

    /**
     * 标准化MinIO路径前缀（确保以"/"结尾）
     * <p>
     * 规则：null或空返回空串；其他确保以"/"结尾
     */
    public static String normalizePrefix(String prefix) {
        if (prefix == null || prefix.isEmpty()) {
            return "";
        }
        return prefix.endsWith(PATH_SEPARATOR) ? prefix : prefix + PATH_SEPARATOR;
    }

    /**
     * 构建相对路径
     * <p>
     * 规则：
     * - 目录路径以"/"结尾：data/images/
     * - 文件路径不以"/"结尾：data/photo.jpg
     */
    public static String buildRelativePath(String prefix, String name, boolean isDirectory) {
        StringBuilder path = new StringBuilder();
        if (prefix != null && !prefix.isEmpty()) {
            path.append(prefix);
            if (!prefix.endsWith(PATH_SEPARATOR)) {
                path.append(PATH_SEPARATOR);
            }
        }
        path.append(name);
        if (isDirectory && !path.toString().endsWith(PATH_SEPARATOR)) {
            path.append(PATH_SEPARATOR);
        }
        return path.toString();
    }

    // ==================== 过滤逻辑 ====================

    /**
     * 通用过滤规则（隐藏文件 + 名称关键词）
     */
    public static boolean shouldFilterByCommonRules(String name, TreeOptions options) {
        // 隐藏文件过滤
        if (!options.isIncludeHiddenFiles() && name.startsWith(".")) {
            return true;
        }
        // 名称关键词过滤
        if (options.getNameFilter() != null && !options.getNameFilter().isEmpty()) {
            return !matchesNameFilter(name, options);
        }
        return false;
    }

    /**
     * 目录过滤检查
     */
    public static boolean shouldFilterDirectory(String dirName, TreeOptions options) {
        if (options.isFilesOnly()) return true;
        return shouldFilterByCommonRules(dirName, options);
    }

    /**
     * 文件过滤检查
     */
    public static boolean shouldFilterFile(String fileName, TreeOptions options) {
        if (options.isDirectoriesOnly()) return true;

        String extension = TreeNode.extractExtension(fileName);
        if (!matchesIncludeExtensions(extension, options)) return true;
        if (matchesExcludeExtensions(extension, options)) return true;

        return shouldFilterByCommonRules(fileName, options);
    }

    /**
     * 检查扩展名是否在包含列表中
     */
    public static boolean matchesIncludeExtensions(String extension, TreeOptions options) {
        if (options.getIncludeExtensions() == null || options.getIncludeExtensions().isEmpty()) {
            return true;
        }
        return extension != null && options.getIncludeExtensions().contains(extension);
    }

    /**
     * 检查扩展名是否在排除列表中
     */
    public static boolean matchesExcludeExtensions(String extension, TreeOptions options) {
        if (options.getExcludeExtensions() == null || options.getExcludeExtensions().isEmpty()) {
            return false;
        }
        return extension != null && options.getExcludeExtensions().contains(extension);
    }

    /**
     * 名称关键词匹配检查
     */
    public static boolean matchesNameFilter(String name, TreeOptions options) {
        String nameToCheck = options.isCaseSensitive() ? name : name.toLowerCase();
        String filterToCheck = options.isCaseSensitive()
                ? options.getNameFilter()
                : options.getNameFilter().toLowerCase();
        return nameToCheck.contains(filterToCheck);
    }

    // ==================== 排序逻辑 ====================

    /**
     * 对子节点列表进行排序
     * <p>
     * 优先级：目录优先 > 排序方式 > 升序/降序
     */
    public static void sortChildren(List<TreeNode> children, TreeOptions options) {
        children.sort((a, b) -> {
            // 优先级1：目录优先
            if (options.isDirectoriesFirst() && a.isDirectory() != b.isDirectory()) {
                return a.isDirectory() ? -1 : 1;
            }
            // 优先级2：按配置排序
            int result = compareNodes(a, b, options);
            // 优先级3：是否倒序
            return options.isDescending() ? -result : result;
        });
    }

    /**
     * 比较两个节点
     */
    private static int compareNodes(TreeNode a, TreeNode b, TreeOptions options) {
        if (options.isSortByModifiedTime()) {
            return compareByModifiedTime(a.getLastModified(), b.getLastModified());
        }
        if (options.isSortBySize()) {
            return Long.compare(a.getSize(), b.getSize());
        }
        if (options.isSortByName()) {
            return a.getName().compareToIgnoreCase(b.getName());
        }
        return 0;
    }

    /**
     * 按修改时间比较（null值排在后面）
     */
    private static int compareByModifiedTime(Date dateA, Date dateB) {
        if (dateA != null && dateB != null) {
            return dateA.compareTo(dateB);
        } else if (dateA != null) {
            return -1;
        } else if (dateB != null) {
            return 1;
        }
        return 0;
    }
}